package com.xxg.renrenproduct.component;

import com.alibaba.fastjson.JSON;
import com.xxg.renrencommon.domain.bean.CarryProductInfo;
import com.xxg.renrencommon.domain.bean.NewGoodsId;
import com.xxg.renrencommon.domain.dao.RenrenShopGoods;
import com.xxg.renrencommon.domain.dao.RenrenShopGoodsOption;
import com.xxg.renrencommon.domain.filedenum.productenum.ProductOptEnum;
import com.xxg.renrencommon.exception.ProductManagerException;
import com.xxg.renrencommon.exception.exceptionenum.ProductExceptionCodeCodeEnum;
import com.xxg.renrenproduct.dao.*;
import com.xxg.renrenproduct.domain.query.GoodsInfo;
import com.xxg.renrenproduct.domain.query.GoodsOptionInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类说明
 *
 * @author szj
 * @date 2021/12/2
 */
@Component
@AllArgsConstructor
@Slf4j
public class ProductComponentImpl implements ProductComponent{
    private final RenrenShopGoodsDao renrenShopGoodsDao;
    private final RenrenShopGoodsOptionDao renrenShopGoodsOptionDao;
    private final RenrenShopGoodsSpecDao renrenShopGoodsSpecDao;
    private final RenrenShopGoodsSpecItemDao renrenShopGoodsSpecItemDao;
    private final RenrenShopGoodsCategoryMapDao renrenShopGoodsCategoryMapDao;
    private final RenrenShopGoodsCategoryDao renrenShopGoodsCategoryDao;
    private final RenrenShopOperationLogDao renrenShopOperationLogDao;
    private final RenrenShopShopDao renrenShopShopDao;

    private enum  OptCodeEnum{
        /**
         * 添加
         */
        ADD("添加", 200000, "api/goods/index/add", "商品-添加"),
        /**
         * 删除
         */
        DELETE("删除", 200015, "api/goods/index/delete", "商品-操作-批量删除")
        ;
        /**
         * 枚举的名称
         */
        private final String name;
        /**
         * 枚举的代码
         */
        private final int value;
        /**
         * action
         */
        private final String action;
        /**
         * title
         */
        private final String title;

        OptCodeEnum(String name, int value, String action, String title) {
            this.name = name;
            this.value = value;
            this.action = action;
            this.title = title;
        }

        public String getName() {
            return name;
        }

        public String getAction() {
            return action;
        }

        public String getTitle() {
            return title;
        }

        public int getValue() {
            return value;
        }

        /**
         * 比较值
         *
         * @param value 需比较参数
         * @return 是否匹配
         */
        public boolean match(Integer value) {
            return value != null && this.value == value;
        }

        @Override
        public String toString() {
            return this.value + "_" + this.name;
        }
    }

    public Object[] copyGoodsToCurrentUserShop(Integer shopId, Integer spuId, List<Integer> categoryIds, Double carryRatio) {
        Object[] arr = new Object[2];
        RenrenShopGoods renrenShopGoods = renrenShopGoodsDao.selectByPrimaryKey(spuId);
        List<RenrenShopGoodsOption> renrenShopGoodsOptions = renrenShopGoodsOptionDao.selectByGoodsId(spuId);
        List<RenrenShopGoodsSpec> renrenShopGoodsSpecs = renrenShopGoodsSpecDao.selectByGoodsId(spuId);
        List<RenrenShopGoodsSpecItem> renrenShopGoodsSpecItems = renrenShopGoodsSpecItemDao.selectByGoodsId(spuId);
        List<RenrenShopGoodsSpecItem> newRenrenShopGoodsSpecItems = new ArrayList<>(renrenShopGoodsSpecItems.size());
        List<RenrenShopGoodsOption> newRenrenShopGoodsOptions = new ArrayList<>(renrenShopGoodsOptions.size());
        renrenShopGoods.setId(null);
        renrenShopGoods.setShopId(shopId);
        if (carryRatio != null) {
            renrenShopGoods.setPrice(renrenShopGoods.getPrice().add(renrenShopGoods.getPrice().multiply(new BigDecimal(carryRatio))).setScale(2, BigDecimal.ROUND_HALF_UP));
            renrenShopGoods.setMinPrice(renrenShopGoods.getMinPrice().add(renrenShopGoods.getMinPrice().multiply(new BigDecimal(carryRatio))).setScale(2, BigDecimal.ROUND_HALF_UP));
            renrenShopGoods.setMaxPrice(renrenShopGoods.getMaxPrice().add(renrenShopGoods.getMaxPrice().multiply(new BigDecimal(carryRatio))).setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        renrenShopGoodsDao.insert(renrenShopGoods);
        Integer newGoodsId = renrenShopGoods.getId();
        log.info("newGoodsId:{}", newGoodsId);
        insertCategoryMap(shopId, categoryIds, newGoodsId);
        HashMap<String, Integer> skuIdMap = new HashMap<>(16);
        if(renrenShopGoodsSpecs != null && renrenShopGoodsSpecs.size() > 0) {
            for (RenrenShopGoodsSpec renrenShopGoodsSpec : renrenShopGoodsSpecs) {
                Integer originSpecId = renrenShopGoodsSpec.getId();
                renrenShopGoodsSpec.setId(null);
                renrenShopGoodsSpec.setGoodsId(newGoodsId);
                renrenShopGoodsSpec.setShopId(shopId);
                renrenShopGoodsSpecDao.insert(renrenShopGoodsSpec);
                Integer specId = renrenShopGoodsSpec.getId();
                renrenShopGoodsSpecItems.forEach(renrenShopGoodsSpecItem -> {
                    if (originSpecId.equals(renrenShopGoodsSpecItem.getSpecId())) {
                        renrenShopGoodsSpecItem.setGoodsId(newGoodsId);
                        renrenShopGoodsSpecItem.setShopId(shopId);
                        renrenShopGoodsSpecItem.setSpecId(specId);
                        newRenrenShopGoodsSpecItems.add(renrenShopGoodsSpecItem);
                    }
                });
            }
            for (RenrenShopGoodsSpecItem renrenShopGoodsSpecItem : newRenrenShopGoodsSpecItems) {
                Integer originSpecItemId = renrenShopGoodsSpecItem.getId();
                renrenShopGoodsSpecItem.setId(null);
                renrenShopGoodsSpecItemDao.insert(renrenShopGoodsSpecItem);
                Integer specItemId = renrenShopGoodsSpecItem.getId();
                renrenShopGoodsOptions.forEach(renrenShopGoodsOption -> {
                    if (String.valueOf(originSpecItemId).equals(renrenShopGoodsOption.getSpecs())) {
                        Integer id = renrenShopGoodsOption.getId();
                        renrenShopGoodsOption.setGoodsId(newGoodsId);
                        renrenShopGoodsOption.setShopId(shopId);
                        renrenShopGoodsOption.setSpecs(String.valueOf(specItemId));
                        renrenShopGoodsOption.setId(null);
                        if (carryRatio != null) {
                            renrenShopGoodsOption.setPrice(renrenShopGoodsOption.getPrice().add(renrenShopGoodsOption.getPrice().multiply(new BigDecimal(carryRatio))).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                        renrenShopGoodsOptionDao.insert(renrenShopGoodsOption);
                        skuIdMap.put(String.valueOf(renrenShopGoodsOption.getId()), id);
//                        newRenrenShopGoodsOptions.add(renrenShopGoodsOption);
                    }
                });
            }
        }
        arr[0] = renrenShopGoods;
        arr[1] = skuIdMap;
        return arr;
    }

    private void insertCategoryMap(Integer shopId, List<Integer> categoryIds, Integer newGoodsId) {
        // 分类映射
        for (Integer categoryId : categoryIds) {
            if (categoryId != null) {
                RenrenShopGoodsCategoryMap renrenShopGoodsCategoryMap = new RenrenShopGoodsCategoryMap();
                renrenShopGoodsCategoryMap.setGoodsId(newGoodsId);
                renrenShopGoodsCategoryMap.setCategoryId(categoryId);
                renrenShopGoodsCategoryMap.setShopId(shopId);
                renrenShopGoodsCategoryMap.setSubShopId(0);
                renrenShopGoodsCategoryMapDao.insert(renrenShopGoodsCategoryMap);
            }
        }
    }

    public void insertOptLog(RenrenShopGoods renrenShopGoods, Integer userId, Integer shopId, OptCodeEnum optCodeEnum, String primary) {
        RenrenShopOperationLog operationLog = new RenrenShopOperationLog();
        operationLog.setIdentifyCode(optCodeEnum.getValue());
        operationLog.setTitle(optCodeEnum.getTitle());
        operationLog.setContent(JSON.toJSONString(renrenShopGoods));
        operationLog.setCreateTime(new Date());
        operationLog.setUid(userId);
        operationLog.setShopId(shopId);
        operationLog.setSubShopId(0);
        operationLog.setRelationIds(String.valueOf(renrenShopGoods.getId()));
        operationLog.setAction(optCodeEnum.getAction());
        operationLog.setIp("121.43.116.228");
        operationLog.setPrimary(primary);
        operationLog.setDirtyPrimary("[]");
        renrenShopOperationLogDao.insert(operationLog);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteGoodsByGoodsId(CarryProductInfo carryProductInfo) {
        Integer goodsId = carryProductInfo.getCarrySpuId();
        Integer userId = carryProductInfo.getUserId();
        Integer shopId = carryProductInfo.getShopId();
        RenrenShopGoods renrenShopGoods = renrenShopGoodsDao.selectByPrimaryKey(goodsId);
        renrenShopGoodsCategoryMapDao.deleteByGoodsId(goodsId);
        renrenShopGoodsOptionDao.deleteByGoodsId(goodsId);
        renrenShopGoodsSpecItemDao.deleteByGoodsId(goodsId);
        renrenShopGoodsSpecDao.deleteByGoodsId(goodsId);
        renrenShopGoodsDao.deleteByPrimaryKey(goodsId);
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
        map2.put("商品id", renrenShopGoods.getId());
        map2.put("商品标题", renrenShopGoods.getTitle());
        map.put("基本设置", map2);
        map.put(ProductOptEnum.CARRY.getFlagName(), ProductOptEnum.CARRY.getFlag());
        map.put(ProductOptEnum.CARRY.getName(), carryProductInfo);
        insertOptLog(renrenShopGoods, userId, shopId, OptCodeEnum.DELETE, JSON.toJSONString(map));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends NewGoodsId> T copyGoodsToCurrentUserShop(Integer userId, Integer shopId, Integer spuId, List<Integer> categoryIds, Double carryRatio, T info) {
        Object[] arr = copyGoodsToCurrentUserShop(shopId, spuId, categoryIds, carryRatio);
        RenrenShopGoods renrenShopGoods = (RenrenShopGoods) arr[0];
        HashMap<String, Integer> skuIdMap = (HashMap<String, Integer>) arr[1];
        info.setNewGoodsId(renrenShopGoods.getId());
        info.setSkuIdMap(skuIdMap);
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
        map2.put("商品id", renrenShopGoods.getId());
        map2.put("商品标题", renrenShopGoods.getTitle());
        map.put("基本设置", map2);
        if (info instanceof CarryProductInfo) {
            map.put(ProductOptEnum.CARRY.getFlagName(), ProductOptEnum.CARRY.getFlag());
        }else {
            map.put(ProductOptEnum.CARRY.getFlagName(), ProductOptEnum.GATHER.getFlag());
        }
        map.put(ProductOptEnum.CARRY.getName(), info);
        insertOptLog(renrenShopGoods, userId, shopId, OptCodeEnum.ADD, JSON.toJSONString(map));
        return info;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer insertProduct(GoodsInfo goodsInfo) throws ProductManagerException {
        RenrenShopShop renrenShopShop = renrenShopShopDao.selectByPrimaryKey(goodsInfo.getShop_id());
        // 查看分类
        String categoryStr = goodsInfo.getCategory();
        String[] split = categoryStr.split("-");
        List<Integer> categoryIds = new ArrayList<>();
        for (int i = 0; i < split.length; i++) {
            Integer categoryId;
            if (i == 0) {
                categoryId = renrenShopGoodsCategoryDao.selectIdByShopIdAndName(goodsInfo.getShop_id(), split[i], 0);
            }else {
                categoryId = renrenShopGoodsCategoryDao.selectIdByShopIdAndName(goodsInfo.getShop_id(), split[i], categoryIds.get(i - 1));
            }
            if (categoryId == null) {
                throw new ProductManagerException(ProductExceptionCodeCodeEnum.NO_CATEGORY.getName() + ":" + categoryStr, ProductExceptionCodeCodeEnum.NO_CATEGORY.getCode());
            }
            categoryIds.add(categoryId);
        }
        RenrenShopGoods renrenShopGoods = createGoods(goodsInfo.getShop_id(), goodsInfo.getHas_option(),
                goodsInfo.getMax_price(), goodsInfo.getMin_price(), goodsInfo.getPrice(), goodsInfo.getStock(),
                goodsInfo.getThumb(), goodsInfo.getThumbAll(), goodsInfo.getTitle());
        renrenShopGoodsDao.insertSelective(renrenShopGoods);
        // 插入分类映射
        insertCategoryMap(renrenShopGoods.getShopId(), categoryIds, renrenShopGoods.getId());
        List<GoodsOptionInfo> options = goodsInfo.getOptions();
        if (options != null && options.size() > 0) {
            Map<String, List<GoodsOptionInfo>> specCollect = options.stream().collect(Collectors.groupingBy(GoodsOptionInfo::getSpecs));
            specCollect.forEach((v, k) -> {
                RenrenShopGoodsSpec spec = createSpec(renrenShopGoods.getId(), renrenShopGoods.getShopId(), renrenShopGoods.getSubShopId(), v);
                renrenShopGoodsSpecDao.insertSelective(spec);
                k.forEach(specItem -> {
                    RenrenShopGoodsSpecItem renrenShopGoodsSpecItem = createSpecItem(spec.getId(), renrenShopGoods.getId(), renrenShopGoods.getShopId(),
                            renrenShopGoods.getSubShopId(), specItem.getTitle());
                    renrenShopGoodsSpecItemDao.insertSelective(renrenShopGoodsSpecItem);
                    RenrenShopGoodsOption renrenShopGoodsOption = createOption(renrenShopGoodsSpecItem.getId(), renrenShopGoods.getId(), renrenShopGoods.getShopId(),
                            renrenShopGoods.getSubShopId(), specItem.getTitle(), specItem.getPrice(), specItem.getStock(), specItem.getThumb());
                    renrenShopGoodsOptionDao.insertSelective(renrenShopGoodsOption);
                });
            });
        }
        // 记录日志
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
        map2.put("商品id", renrenShopGoods.getId());
        map2.put("商品标题", renrenShopGoods.getTitle());
        map.put("基本设置", map2);
        insertOptLog(renrenShopGoods, renrenShopShop.getUserId(), renrenShopShop.getId(), OptCodeEnum.ADD, JSON.toJSONString(map));
        return renrenShopGoods.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteGoodsByGoodsId(Integer goodsId) {
        RenrenShopGoods renrenShopGoods = renrenShopGoodsDao.selectByPrimaryKey(goodsId);
        RenrenShopShop renrenShopShop = renrenShopShopDao.selectByPrimaryKey(renrenShopGoods.getShopId());
        renrenShopGoodsCategoryMapDao.deleteByGoodsId(goodsId);
        renrenShopGoodsOptionDao.deleteByGoodsId(goodsId);
        renrenShopGoodsSpecItemDao.deleteByGoodsId(goodsId);
        renrenShopGoodsSpecDao.deleteByGoodsId(goodsId);
        renrenShopGoodsDao.deleteByPrimaryKey(goodsId);
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        LinkedHashMap<String, Object> map2 = new LinkedHashMap<>();
        map2.put("商品id", renrenShopGoods.getId());
        map2.put("商品标题", renrenShopGoods.getTitle());
        map.put("基本设置", map2);
        insertOptLog(renrenShopGoods, renrenShopShop.getUserId(), renrenShopGoods.getShopId(), OptCodeEnum.DELETE, JSON.toJSONString(map));
    }

    private RenrenShopGoodsOption createOption(Integer specId, Integer goodsId, Integer shopId, Integer subShopId, String title, BigDecimal price, Integer stock, String thumb) {
        RenrenShopGoodsOption renrenShopGoodsOption = new RenrenShopGoodsOption();
        renrenShopGoodsOption.setShopId(shopId);
        renrenShopGoodsOption.setSubShopId(subShopId);
        renrenShopGoodsOption.setGoodsId(goodsId);
        renrenShopGoodsOption.setTitle(title);
        renrenShopGoodsOption.setPrice(price);
        renrenShopGoodsOption.setStock(stock);
        renrenShopGoodsOption.setSpecs(specId + "");
        renrenShopGoodsOption.setThumb(thumb);

        return renrenShopGoodsOption;
    }

    private RenrenShopGoodsSpecItem createSpecItem(Integer specId, Integer goodsId, Integer shopId, Integer subShopId, String title) {
        RenrenShopGoodsSpecItem renrenShopGoodsSpecItem = new RenrenShopGoodsSpecItem();
        renrenShopGoodsSpecItem.setShopId(shopId);
        renrenShopGoodsSpecItem.setSubShopId(subShopId);
        renrenShopGoodsSpecItem.setGoodsId(goodsId);
        renrenShopGoodsSpecItem.setSpecId(specId);
        renrenShopGoodsSpecItem.setTitle(title);

        return renrenShopGoodsSpecItem;
    }

    private RenrenShopGoodsSpec createSpec(Integer goodsId, Integer shopId, Integer subShopId, String title) {
        RenrenShopGoodsSpec renrenShopGoodsSpec = new RenrenShopGoodsSpec();
        renrenShopGoodsSpec.setShopId(shopId);
        renrenShopGoodsSpec.setSubShopId(subShopId);
        renrenShopGoodsSpec.setGoodsId(goodsId);
        renrenShopGoodsSpec.setTitle(title);
        renrenShopGoodsSpec.setImageChecked(0);
        return renrenShopGoodsSpec;
    }

    private RenrenShopGoods createGoods(Integer shopId, Boolean hasOption,
                                        BigDecimal maxPrice, BigDecimal minPrice, BigDecimal price, Integer stock, String thumb,
                                        String thumbAll, String title) {
        RenrenShopGoods renrenShopGoods = new RenrenShopGoods();
        renrenShopGoods.setShopId(shopId);
        renrenShopGoods.setSubShopId(0);
        renrenShopGoods.setStatus(1);
        renrenShopGoods.setCreateTime(new Date());
        renrenShopGoods.setTitle(title);
        renrenShopGoods.setThumb(thumb);
        renrenShopGoods.setThumbAll(thumbAll);
        renrenShopGoods.setStock(stock);
        renrenShopGoods.setPrice(price);
        renrenShopGoods.setMinPrice(minPrice);
        renrenShopGoods.setMaxPrice(maxPrice);
        renrenShopGoods.setHasOption(hasOption);
        renrenShopGoods.setContent("");
        renrenShopGoods.setExtField(createExtField());
        renrenShopGoods.setParams("[]");
        renrenShopGoods.setReductionType(1);

        return renrenShopGoods;
    }

    private String createExtField() {
        return "{\"show_sales\":\"0\",\"show_stock\":\"1\",\"invoice\":\"0\",\"refund\":\"1\",\"return\":\"1\",\"exchange\":\"1\",\"is_delivery_pay\":\"0\",\"auto_putaway\":\"0\",\"single_max_buy\":\"1\",\"single_min_buy\":\"1\",\"max_buy\":\"1\",\"buy_limit\":\"0\",\"putaway_time\":\"0NaN-NaN-NaN NaN:NaN:NaN\",\"title_type\":\"0\",\"title\":\"\",\"share_description\":\"\",\"logo_type\":\"\",\"logo\":\"\",\"wxapp_logo\":\"\",\"deduction_gift_card_type\":\"0\",\"deduction_gift_card\":\"\",\"deduction_gift_card_repeat\":\"0\",\"note\":\"\",\"offaway_time\":\"0NaN-NaN-NaN NaN:NaN:NaN\",\"buy_button_settings\":[],\"buy_button_type\":\"0\"}";
    }

}
